package com.shpng.cheapenglish.servlet;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.shpng.cheapenglish.util.GetExceptionStack;
import com.shpng.cheapenglish.util.ParseParameter;
import com.shpng.cheapenglish.util.StringUtils;

public class SimpleDispatcherServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2866109385307092663L;

	private static final String actionPackage = "com.shpng.cheapenglish.action";

	@SuppressWarnings("unchecked")
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		req.setCharacterEncoding("utf-8");
		resp.setHeader("Content-Type", "text/html; charset=utf-8");
		Map<String, String[]> params = req.getParameterMap();
		String uri = req.getRequestURI();
		String email = (String) req.getSession().getAttribute("email");
		if (StringUtils.isEmpty(email) && !uri.contains("login")
				&& !uri.contains("register")) {
			req.getRequestDispatcher("/pages/welcome.jsp").forward(req, resp);
			return;
		}

		String cp = req.getContextPath();
		String actionName = null;
		String actionMethod = null;
		if (uri.contains("!")) {
			actionName = uri.substring(cp.length() + 1, uri.lastIndexOf("!"));
			actionMethod = uri.substring(uri.lastIndexOf("!"),
					uri.lastIndexOf(".do"));
		} else {
			actionName = uri.substring(cp.length() + 1, uri.lastIndexOf(".do"));
			actionMethod = "execute";
		}
		actionName = actionName.substring(0, 1).toUpperCase()
				+ actionName.substring(1) + "Action";
		// System.out.println(actionName);
		// System.out.println(actionMethod);
		actionName = actionPackage + "." + actionName;
		Class<?> clazz = null;
		try {
			clazz = Class.forName(actionName);
			Method[] methods = clazz.getMethods();
			Map<String, Method> methodMaps = new HashMap<String, Method>();
			for (Method method : methods) {
				if (method.getName().contains("get")
						|| method.getName().contains("set")) {
					methodMaps.put(method.getName(), method);
				}
			}

			Object action = clazz.newInstance();

			Set<String> paramKeys = params.keySet();
			for (String paramKey : paramKeys) {
				String propertySetMethod = "set"
						+ paramKey.substring(0, 1).toUpperCase()
						+ paramKey.substring(1);
				String[] paramValues = params.get(paramKey);
				if (paramValues == null || paramValues.length <= 0)
					continue;
				Method method = methodMaps.get(propertySetMethod);
				if (method == null)
					continue;

				Type[] types = method.getGenericParameterTypes();
				if (types.length <= 0 || types.length > 1)
					continue;
				Object value = ParseParameter.getInstance().parse(types[0],
						params.get(paramKey));
				method.invoke(action, value);
			}
			String result = null;

			result = (String) clazz.getMethod(actionMethod,
					HttpServletRequest.class, HttpServletResponse.class)
					.invoke(action, req, resp);
			if (result != null)
				req.getRequestDispatcher(result).forward(req, resp);
		} catch (Exception e) {
			resp.getWriter().print(GetExceptionStack.e(e));
			e.printStackTrace();
		}
		// catch (SecurityException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (IllegalAccessException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (InvocationTargetException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (NoSuchMethodException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (InstantiationException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (ClassNotFoundException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (ParseException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(req, resp);
	}

}
